from market.models import Strategy, Asset, Player, Fund, WebSiteComment
from market.models import History, AssetForHistory, StrategyForHistory, PlayerPortfolioForHistory
from market.models import DigitalContract, BidOnContract, OfferOnContract, LiquidityToken, TradedContract, LastVisitedContract
from market.marketData import MarketData
from django.utils import simplejson
from market.strategyAndFundHelper import getFundMtM, getPortfolioMtM
import os, os.path, shutil, json



##################################################################################################
# try to get the field 'isAvailableForStandardStrategy' from the asset. this field does not exist in old bases
def getAvailableForStandardStrategy( asset ):
    tmp = True
    try:
        tmp = asset.isAvailableForStandardStrategy
    except:
        tmp = True
    return tmp

##################################################################################################
# try to get the field valueMultiplier from the asset. this field does not exist in old bases
def getValueMultiplier( asset ):
    tmp = 1
    try:
        tmp =asset.valueMultiplier
    except:
        tmp = 1
    return tmp

##################################################################################################
# try to get the field fixValue from the asset. this field does not exist in old bases
def getFixValue( asset ):
    try:
        return asset.fixValue
    except:
        return -1
    
##################################################################################################
# try to get the field IsStandard from the asset. this field does not exist in old bases
def getIsStandard( asset ):
    try:
        return asset.isStandard
    except:
        return True

##################################################################################################
# try to get the field IsStandard from the asset. this field does not exist in old bases
def getDescription( asset ):
    try:
        return asset.description
    except:
        return ""

##################################################################################################
def getPosterName( comment ):
    try:
        return comment.poster.userBeingThisPlayer.username
    except:
        try:
            return comment.poster.name
        except:
            raise Exception('failed to retrieve comment poster name')

##################################################################################################
def getBettingPlayerName( history ):
    try:
        return history.bettingPlayerName
    except:
        return 'John Do'

##################################################################################################
def getHistoryActionTaken( history ):
    try:
        return history.actionTaken
    except:
        return 'unknown'

##################################################################################################
def getMtMPerc( MtMStrat, totalMtM ):
    if totalMtM == 0:
        return 0
    return 100 * MtMStrat / totalMtM



##################################################################################################
# return the bank account value of the portfolio of a player
def getTotalMtM( player, market ):
        if player.mainStrategy.betroom.roomType == 1:
                buyingFund = Fund.objects.get( player = player )
                return buyingFund.numberOfAssetsInFund
        return getPortfolioMtM( player, market )


##################################################################################################
# this command take the object in base and create associated text file.
# the data saved are those which will allow to reconstruct the base in the same state
def saveRoomToFiles(mypath0, betroom):
    
        # handle the folders, copy the file to "_old", if they already exists
        mypath = os.path.join( mypath0, betroom.name )
        # create the dir if does not exist
        if not os.path.exists(mypath):
            os.mkdir(mypath)
        else:# the dir exists and we copy it to "_old"
            mypath_old = os.path.join( mypath0, betroom.name + '_old' )
            if os.path.exists(mypath_old):
                shutil.rmtree(mypath_old) 
            shutil.copytree(mypath, mypath_old)

        # register betroom
        fileName = os.path.join( mypath, 'betroom.txt')
        f = open( fileName , 'w+')
        f.write( json.dumps( { 'name':betroom.name,
            'personInCharge':betroom.personInCharge.username,
            'description':betroom.description,
            'status':betroom.status,
            'roomType':betroom.roomType,
            'password':betroom.password} , sort_keys=True, indent=4 ) )
        f.close()

        # register strategies
        fileName = os.path.join( mypath, 'Strategies.txt')
        f = open( fileName , 'w+')
        f.write(json.dumps( { 'strategies':[{
            'name':s.name,
            'assetInStrat':[{
                'assetName': ais.asset.name,
                'assetPerc': 100 * ais.assetPercentageInStrategy
                } for ais in s.assetpercentageinstrategy_set.all()]
            } for s in Strategy.objects.filter( betroom = betroom )] }, sort_keys=True, indent=4 ))
        f.close()
        
        # register assets
        fileName = os.path.join( mypath, 'Assets.txt')
        f = open( fileName, 'w+')
        f.write(json.dumps( { 'assets':[{
            'name':a.name,
            'isAvailableForStandardStrategy': getAvailableForStandardStrategy( a ),
            'valueMultiplier': getValueMultiplier( a ),
            'fixValue': getFixValue( a ),
            'description':getDescription( a ),
            'isStandard':getIsStandard( a )
            } for a in Asset.objects.filter( betroom = betroom )] }, sort_keys=True, indent=4 ))
        f.close()

        # register playerData
        m = MarketData(betroom)
        for p in Player.objects.filter(mainStrategy__betroom = betroom):
            fileName = os.path.join( mypath, p.userBeingThisPlayer.username+'player.txt')
            f = open( fileName, 'w+')
            totalMtM = getTotalMtM( p, m )
            f.write(json.dumps( {
                'name':p.userBeingThisPlayer.username,
                'mainStratName':p.mainStrategy.name,
                'mtm': totalMtM,
                'fundInPortfolio':[{
                    'stratName': ff.strategy.name,
                    'fundMtMSetPerc': 100 * ff.fundTargetPercentageInPortfolio,
                    'fundMtMCurrentPerc': getMtMPerc( getFundMtM(p, m, ff.strategy), totalMtM )
                } for ff in Fund.objects.filter( player = p )]
                }, sort_keys=True, indent=4))
            f.close()


        # register the history
        fileName = os.path.join( mypath, 'history.txt')
        f = open( fileName, 'w+')
        f.write(json.dumps( { 'history':[{
            'time':h.time.strftime("%d/%m/%Y %H:%M:%S"),
            'bettingPlayerName':getBettingPlayerName( h ),
            'actionTaken':getHistoryActionTaken( h ),
            'assets': [{'assetName':a.asset.name, 'assetPrice':a.price} for a in AssetForHistory.objects.filter(history=h)],
            'strategies': [{'strategyName':s.strategy.name,
                            'strategyMtM':s.strategyMtM,
                            'strategyPerfSinceLastHistoryDate':s.strategyPerfSinceLastHistoryDate,
                            'numberOfPlayersInvestedInTheStrategy':s.numberOfPlayersInvestedInTheStrategy,
                            'totalNumberOfAssetInvestedInTheStrategy':s.totalNumberOfAssetInvestedInTheStrategy
                            } for s in StrategyForHistory.objects.filter(history=h)],
            'playerPortfolios': [{'playerName':p.player.userBeingThisPlayer.username,
                            'portfolioMtM':p.portfolioMtM,
                            'investementInMainStrategyPercentage':p.investementInMainStrategyPercentage,
                            'numberOfStrategies':p.numberOfStrategies
                            } for p in PlayerPortfolioForHistory.objects.filter(history=h)]
            } for h in History.objects.filter(betroom = betroom)] }, sort_keys=True, indent=4 ))
        f.close()

        
        if betroom.roomType == 1:
            saveContractRoomToFiles(mypath, betroom)

        print( betroom.name + ' has been successfully saved in %s' %mypath)



##################################################################################################
# do the job forr a room by contract
def saveContractRoomToFiles(mypath, betroom):

        # register contracts
        fileName = os.path.join( mypath, 'Contracts.txt')
        f = open( fileName , 'w+')
        f.write(json.dumps( { 'contracts':[{
            'name':c.name,
            'issuer':c.issuer.userBeingThisPlayer.username,
            'description': c.description,
            'expiry':c.expiry.strftime("%d/%m/%Y %H:%M:%S"),
            'settlementStatus':c.settlementStatus
            } for c in DigitalContract.objects.filter( issuer__mainStrategy__betroom = betroom )] }, sort_keys=True, indent=4 ))
        f.close()

        # register traded contract
        fileName = os.path.join( mypath, 'TradedContracts.txt')
        f = open( fileName , 'w+')
        f.write(json.dumps( { 'tradedContracts':[{
            'name':tc.contract.name,
            'buyer':tc.buyer.userBeingThisPlayer.username,
            'seller':tc.seller.userBeingThisPlayer.username,
            'tradeDate': tc.tradeDate.strftime("%d/%m/%Y %H:%M:%S"),
            'tradedPrice': tc.tradedPrice
            } for tc in TradedContract.objects.filter( contract__issuer__mainStrategy__betroom = betroom )] }, sort_keys=True, indent=4 ))
        f.close()

        
        # register the liquidity token
        fileName = os.path.join( mypath, 'LiquidityTokens.txt')
        f = open( fileName , 'w+')
        f.write(json.dumps( { 'liquidityTokens':[{
            'contract':ldqtk.offer.contract.name,
            'holder':ldqtk.offer.player.userBeingThisPlayer.username,
            'offer':ldqtk.offer.price,
            'bid': ldqtk.bid.price
            } for ldqtk in LiquidityToken.objects.filter( offer__contract__issuer__mainStrategy__betroom = betroom )] }, sort_keys=True, indent=4 ))
        f.close()

